/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.jtalker.client.plugins.TicTacToe;

/**
 * 
 * @author christoph
 */
public class TTTGameLogic {
	private static int SYMBOL_X = 1;
	private static int SYMBOL_O = 2;
	private static int EMPTY = 0;
	private int userPlaying = SYMBOL_X;
	private int enemyPlaying = SYMBOL_O;

	private int gamesArea[] = { EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY };
	private String winCombinations[] = { "123", "456", "789", "147", "258", "369", "159", "357" };

	// private static int ENEMY_REMOTE = 0;
	private static int ENEMY_AI = 1;
	private int enemyType = 1;

	private TTTWindow myGameWindow;
	private boolean waitingForUser = true;
	private int aIQuality = 0;

	private boolean gameEnds = false;
	public String lastWinCombi;

	public TTTGameLogic(TTTWindow gameWindow) {
		this.myGameWindow = gameWindow;
	}

	public void startGame(boolean userBegins, int userSymbol, int enemyType, int aIQuality) {
		System.out.println("----> in TTTGameLogic.startGame()");

		this.lastWinCombi = "";
		this.enemyType = enemyType;
		this.userPlaying = userSymbol;

		if (this.userPlaying == SYMBOL_X) {
			this.enemyPlaying = SYMBOL_O;
		} else {
			this.enemyPlaying = SYMBOL_X;
		}
		this.aIQuality = aIQuality;
		this.gameEnds = false;

		for (int i = 1; i < 10; i++) {
			this.gamesArea[i - 1] = EMPTY;
			this.myGameWindow.setSymbolOnButton(i, EMPTY);
		}

		if (this.enemyType == ENEMY_AI) {
			System.out.println("AI quality: " + this.aIQuality);
		}
		if (userSymbol == SYMBOL_O) {
			this.enemyPlaying = SYMBOL_X;
		}
		this.waitingForUser = userBegins;

		if (userBegins) {
			this.setGameStatusString("Waiting for LOCAL...");
		} else {
			this.setGameStatusString("Waiting for ENEMY...");
		}
		System.out.println("Starting GAME...");
		/**
		for (int i = 1; i < 10; i++) {
			this.myGameWindow.setSymbolOnButton(i, EMPTY);
		}
		*/
		if (!this.waitingForUser && this.enemyType == ENEMY_AI) {
			System.out.println("AI");
			this.AITurn(true);
		}
	}

	public void cancelGame() {
		for (int i = 1; i < 10; i++)
			this.myGameWindow.setSymbolOnButton(i, EMPTY);

		this.gameEnds = true;
	}

	public boolean checkForGamesEnd() {
		int winner = this.checkFieldForWinner();
		if (winner > 0) {
			// GAME ENDS HERE - we have a winner
			if (winner == this.userPlaying) {
				this.myGameWindow.gameEnds(0);
			} else {
				this.myGameWindow.gameEnds(1);
			}

			return true;
		} else if (winner == -2) {
			// // GAME ENDS HERE - Tied
			this.myGameWindow.gameEnds(-1);
			return true;
		}

		return false;
	}

	public boolean userAction(int index) {
		if (this.gameEnds) {
			this.setGameStatusString("Start a new game first!");
			return false;
		}

		if (!this.waitingForUser) {
			this.setGameStatusString("It's not yor turn! Wait for ENEMY.");
			return false;
		}

		if (this.gamesArea[index - 1] == EMPTY) {
			this.gamesArea[index - 1] = this.userPlaying;
			this.myGameWindow.setSymbolOnButton(index, this.userPlaying);
		} else {
			this.setGameStatusString("Allready used - choose another field!");
			return false;
		}

		this.waitingForUser = false;

		if (this.checkForGamesEnd()) {
			return true;
		}
		this.setGameStatusString("Waiting for ENEMY...");

		if (this.enemyType == ENEMY_AI) {
			this.AITurn(false);

			if (this.checkForGamesEnd()) {
				return true;
			}
		}

		return true;
	}

	/**
	 * 校验是否有获胜者.
	 * @return
	 */
	private int checkFieldForWinner() {
		int checkSymbol = SYMBOL_X;
		/**
		 * 循环两次，分别校验XXX和OOO，有成的，则成功。
		 */
		for (int j = 0; j < 2; j++) {
			for (int i = 0; i < this.winCombinations.length; i++) {
				if (this.getWinCombinationField(i, 0) == checkSymbol
						&& this.getWinCombinationField(i, 1) == checkSymbol
						&& this.getWinCombinationField(i, 2) == checkSymbol) {

					System.out.println("WINNER!");
					this.lastWinCombi = this.winCombinations[i];
					this.setGameStatusString("The winner is: " + this.myGameWindow.symbols[checkSymbol]);
					this.gameEnds = true;
					return checkSymbol;
				}
			}
			checkSymbol = SYMBOL_O;
		}

		// No winner now - check for full game area
		for (int k = 0; k < this.gamesArea.length; k++) {
			if (this.gamesArea[k] == EMPTY) {
				return -1;
			}
		}

		// No empty field found - end game tied
		this.setGameStatusString("Tied");
		return -2;
	}

	/**
	 * 设置游戏进行状态.
	 * @param status
	 */
	private void setGameStatusString(String status) {
		this.myGameWindow.setStatusString(status);
	}

	
	/**
	 * 获取方格内的值,Empty-0 X-1 O-2.
	 * @param combi
	 * @param field
	 * @return
	 */
	private int getWinCombinationField(int combi, int field) {
		return this.gamesArea[Integer.parseInt(this.winCombinations[combi].substring(field, field + 1)) - 1];
	}

	/**
	 * 获取方格的索引号.1.2.3.4.5..9.
	 * @param combi
	 * @param field
	 * @return
	 */
	private int getWinCombinationFieldIndex(int combi, int field) {
		return Integer.parseInt(this.winCombinations[combi].substring(field, field + 1));
	}

	public boolean externalAction(int index) {
		if (this.waitingForUser){
			return false;
		}
		if (this.gamesArea[index - 1] == EMPTY) {
			this.gamesArea[index - 1] = this.enemyPlaying;
			this.myGameWindow.setSymbolOnButton(index, this.enemyPlaying);
			this.waitingForUser = true;

			if (this.checkForGamesEnd()){
				return true;
			}
			
			this.setGameStatusString("Waiting for YOU...");
			return true;
		}

		return false;
	}

	private void AITurn(boolean firstTurn) {
		if (firstTurn) {
			if (this.externalAction(5)) {
				return;
			}
		}

		int sum = 0;
		int content = EMPTY;
		int empty = -1;

		// Search for a win combi
		if (this.aIQuality < 2) {

			for (int i = 0; i < this.winCombinations.length; i++) {
				for (int j = 0; j < 3; j++) {
					content = this.getWinCombinationField(i, j);
					if (content == this.enemyPlaying)
						sum++;
					if (content == EMPTY)
						empty = j;
				}

				if (sum > 1 && empty >= 0) {
					// Use a free possible combination
					System.out.println("AI found a winner combi: " + i + ", empty:"
							+ this.getWinCombinationFieldIndex(i, empty));
					if (this.externalAction(this.getWinCombinationFieldIndex(i, empty)))
						return;

				} else {
					sum = 0;
					empty = -1;
				}
			}
		}

		// Check for some defense need
		sum = 0;
		content = EMPTY;
		empty = -1;
		for (int i = 0; i < this.winCombinations.length; i++) {
			for (int j = 0; j < 3; j++) {
				content = this.getWinCombinationField(i, j);
				if (content == this.userPlaying)
					sum++;
				if (content == EMPTY)
					empty = j;
			}

			if (sum > 1 && empty >= 0) {
				// We must block!
				System.out.println("AI is blocking. combi: " + i + ", empty:"
						+ this.getWinCombinationFieldIndex(i, empty));
				if (this.externalAction(this.getWinCombinationFieldIndex(i, empty)))
					return;

			} else {
				sum = 0;
				empty = -1;
			}
		}

		// Now use the own chance...
		if (this.aIQuality == 0) {
			sum = 0;
			content = EMPTY;
			empty = -1;
			for (int i = 0; i < this.winCombinations.length; i++) {
				for (int j = 0; j < 3; j++) {
					content = this.getWinCombinationField(i, j);
					if (content == this.enemyPlaying)
						sum++;
					if (content == EMPTY)
						empty = j;
					if (content == this.userPlaying)
						sum--;
				}

				if (sum > 0 && empty >= 0) {
					// Use a free possible combination
					System.out.println("AI found a combi: " + i + ", empty:"
							+ this.getWinCombinationFieldIndex(i, empty));
					if (this.externalAction(this.getWinCombinationFieldIndex(i, empty)))
						return;

				} else {
					sum = 0;
					empty = -1;
				}
			}
		}

		// Still no good turn - use the middle field
		if (this.gamesArea[4] == EMPTY) {
			System.out.println("AI has no better idea than using the fild in the middle.");
			this.externalAction(4 + 1);
			return;
		}

		// Find next free field
		for (int k = 0; k < this.gamesArea.length; k++) {
			if (this.gamesArea[k] == EMPTY) {
				System.out.println("AI has no better idea than using the next free field.");
				this.externalAction(k + 1);
				return;
			}
		}
	}
}
